/* Jerrad Zonna
 * Arena Battler Game
 * A game that a player can purchase weapons
 * and fight for more cash to progress
 * further improvment details in comment blocks listed TODO
*/

#include "Game.h"

using namespace std;

// global varibles for data input
int input;
string name;

// function deffinitions
void LoadGame(void);
void SaveGame(void);
void Menu(void);
void Store(void);
void Arena(void);
void Inventory(void);
template <class type1, class type2> void Damage(type1 &t1, type2 t2);
bool BattleOver(Enemy);
int InputCheck(int);
string InputCheck(string);
int RandomNumber(int,int);

/*
* main
* no parameters
* prompts the user for a new game or load character data
* executes Menu which will run the game loop
* on Menu exit SaveGame executes then program ends
*/
int main()
{
	srand(time(0));
	
	Game* theGame = new Game();
	theGame->Run();

	//Menu();
	//SaveGame();
	
	return 0;
}

/*
* Menu
* no parameters
* main program loop displays menu screen and prompts user for input
* on selected choice selection is executed and loop conntinues 
* till until the player wants to exit

void Menu()
{
	do
	{
		input = InputCheck(input);

		switch(input)
		{
			case 1:
				Inventory();
				break;
			case 2:
				Arena();
				break;
			case 3:
				Store();
				break;
			default:
				break;
		}
	}while(input != 0);
}

/*
* Store
* no parameters
* creates and displays items for sale 
* when item is bought item is placed into inventory

void Store()
{
	// TODO:
	//		?Generate and store items into array w/o need for variables
	//		Create some weapons and armor with randomly generated stats
	//		When item is bought place item in next available space in inventory
	//			if inventory is full prompt to replace or cancel transaction
	//				place item in that spot
	
	Armor storeArmor[2];
	Weapon storeWeapons[3];

	Armor a1 ("Armor of Light", 150, 50);
	Armor a2 ("Armor of Darkness", 250, 125);
	Weapon w1 ("Axe of Blight", 75, 30);
	Weapon w2 ("Hammer of Dongo", 100, 50);
	Weapon w3 ("Spear of Foo", 150, 70);
	Weapon epic ("Holy Handgrenade", 300, 500);

	storeArmor[0] = a1;
	storeArmor[1] = a2;
	storeWeapons[0] = w1;
	storeWeapons[1] = w2;
	storeWeapons[2] = w3;

	system("cls");
	cout << "Welcome to the Store! \nChoose an item from below:" << endl;
	cout << "Exit enter <0>\n" << endl;

	for(int i = 0; i < 2; i++)
	{
		if(storeArmor[i].GetItemName() != "")
		{
			string temp = "";
			int DEF = 0;
			double cost = 0;

			temp = storeArmor[i].GetItemName();
			DEF = storeArmor[i].GetDefense();
			cost = storeArmor[i].GetCost();

			cout << i + 1 << " => ";
			cout <<  temp << "\t\tDEF: ";

			if(DEF >= 100)
			{
				temp = " \t$";
			}
			else
			{
				temp = "\t\t$";
			}

			cout << DEF << temp << cost << endl;
		}
	}

	for(int i = 0; i < 3; i++)
	{
		if(storeWeapons[i].GetItemName() != "")
		{
			string temp = "";
			int AP = 0;
			double cost = 0;

			temp = storeWeapons[i].GetItemName();
			AP = storeWeapons[i].GetAttackPower();
			cost = storeWeapons[i].GetCost();

			cout << i + 3 << " => ";
			cout <<  temp << "\t\tAP: ";

			if(AP >= 100)
			{
				temp = " \t$";
			}
			else
			{
				temp = "\t\t$";
			}

			cout << AP << temp << cost << endl;
		}
	}
	cout << "6 => 25 HP\t\t\t\t\t$50" << endl;
	cout << "\n" << p1.GetName() << "'s" << " Total $" << p1.GetCash();

	cout << "\n\nSelect an item to purchase => ";
	input = InputCheck(input);
	switch(input)
	{
		case 1:
			if(p1.GetCash() >= a1.GetCost())
			{
				for(int i = 0; i < 2; i++)
				{
					if(p1.armors[i].GetCost() == 0)
					{
						p1.armors[0] = a1;
						p1.SetCash(p1.GetCash() - a1.GetCost());
						break;
					}
					else
					{
						cout << "full inventory";
						break;
					}
				}
				break;
			}
			else
			{
				cout << "Not enough cash!";
				break;
			}
		case 2:
			if(p1.GetCash() >= a2.GetCost())
			{
				for(int i = 0; i < 2; i++)
				{
					if(p1.armors[i].GetCost() == 0)
					{
						p1.armors[i] = a2;
						p1.SetCash(p1.GetCash() - a2.GetCost());
						break;
					}
					else
					{
						cout << "full inventory";
						break;
					}
				}
				break;
			}
			else
			{
				cout << "Not enough cash!";
				break;
			}
		case 3:
			if(p1.GetCash() >= w1.GetCost())
			{
				for(int i = 0; i < 3; i++)
				{
					if(p1.weapons[i].GetCost() == 0)
					{
						p1.weapons[i] = w1;
						p1.SetCash(p1.GetCash() - w1.GetCost());
						break;
					}
					else
					{
						cout << "full inventory";
						break;
					}
				}
				break;
			}
			else	
			{
				cout << "Not enough cash!";
				break;
			}
		case 4:
			if(p1.GetCash() >= w2.GetCost())
			{
				for(int i = 0; i < 3; i++)
				{
					if(p1.weapons[i].GetCost() == 0)
					{
						p1.weapons[i] = w2;
						p1.SetCash(p1.GetCash() - w1.GetCost());
						break;
					}
					else
					{
						cout << "full inventory";
						break;
					}
				}
				break;
			}
			else
			{
				cout << "Not enough cash!";
				break;
			}
		case 5:
			if(p1.GetCash() >= w3.GetCost())
			{
				for(int i = 0; i < 3; i++)
				{
					if(p1.weapons[i].GetCost() == 0)
						{
						p1.weapons[i] = w3;
						p1.SetCash(p1.GetCash() - w1.GetCost());
						break;
					}
					else
					{
						cout << "full inventory";
						break;
					}
				}
				break;
			}
			else
			{
				cout << "\nNot enough cash!";
				break;
			}
		case 6:
			if(p1.GetCash() >= 50)
			{
				p1.SetHealthModifier(p1.GetHealthModifier() + 25);
				p1.SetHealth(p1.GetBaseHealth() + p1.GetHealthModifier());
				p1.SetCash(p1.GetCash() - 50);
				break;
			}
			else
			{
				cout << "\nNot enough cash!";
				break;
			}
			break;
		case 777:
			p1.weaponEquiped = epic;
			break;
		default:
			input = -1;
			break;
	}
	cin;
	cin.clear();
	cin.ignore(100,'\n');
}

/*
* Arena
* no parameters
* places the player in a battle with an enemy
* battles is not over till the conditions are met
* player is granted money if the player wins and the health is reset

void Arena()
{
	// TODO:
	//		Scale enemy to player level
	//		Scale reward based on enemy level
	//		Scale enemy weapon/armor to player level

	system("cls");

	Enemy *monster1 = new Enemy ("Goblin");
	//Enemy *monster1 = new Enemy ("Hitler");
	monster1->SetHealth(100);//RandomNumber(250,100)
	Weapon w ("Cracked Club", 10, RandomNumber(20,10));
	Armor a ("Green Tunic", 15, RandomNumber(20,10));
	monster1->weaponEquiped = w;
	monster1->armorEquiped = a;

	do
	{
		system("cls");
		cout << p1.GetName() << "\t\t\t\t\t" << monster1->GetName() << endl;
		cout << "HP " << p1.GetHealth() << "\t\t\t\t\t";
		cout << "HP " << monster1->GetHealth() << endl;
		cout << "\nActions:\n\n";
		cout << "1 = Attack\n";
		cout << "2 = Inventory\n";

		input = InputCheck(input);

		switch(input)
		{
			case 1:
				Damage(*monster1, p1);
				break;
			case 2:
				Inventory();
				break;
			default:
				input = -1;
				break;
		}

		Damage(p1, *monster1);

	}while(!BattleOver(*monster1));

	p1.SetHealth(p1.GetBaseHealth() + p1.GetHealthModifier());

	if(monster1->GetHealth() <= 0)
	{
		p1.SetCash(p1.GetCash() + RandomNumber(50, 100));
	}

}

/*
* Damage
* Takes in entity refrence and another entity
* Deals damage to entity t1

template <class type1, class type2> void Damage(type1 &t1, type2 t2)
{
	int initAP = t2.weaponEquiped.GetAttackPower();
	int initDef = t1.armorEquiped.GetDefense();
	int damage = 0;

	if(initDef == initAP)
		damage = 0;
	else if(initDef > initAP)
		damage = 0;
	else if(initDef < initAP)
		damage = initAP - initDef;

	t1.SetHealth(t1.GetHealth() - damage);
}

/* 
* BattleOver 
* Enemy monster1
* checks to make sure either p1 or enemy is dead
*
bool BattleOver(Enemy mstr)
{
	if(p1.GetHealth() > 0 && mstr.GetHealth() > 0)
		return false;
	else if(p1.GetHealth() <= 0 || mstr.GetHealth() <= 0)
		return true;
	else
		return false;
}

/*
* Inventory
* no parameters
* displays the players inventory and asks the player
* if they wish to equip weapons and armor

void Inventory()
{
	system("cls");
	Weapon wTemp;
	Armor aTemp;
	int itemEquipNumber = 0;
	string temp = p1.GetName();
	cout << temp << "'s Inventory\n" << endl;
	cout << "Currently Equiped:" << endl;
	cout << "\n" << p1.weaponEquiped.GetItemName() << "\tAP: ";
	cout << p1.weaponEquiped.GetAttackPower() << endl; 
	cout << p1.armorEquiped.GetItemName() << "\tDEF: ";
	cout << p1.armorEquiped.GetDefense() << endl; 

	cout << "\nWeapons:" << endl;
	for(int i = 0; i < 3; i++)
	{
		if(p1.weapons[i].GetItemName() != "")
		{
			string itemName = p1.weapons[i].GetItemName();
			int weaponAP = p1.weapons[i].GetAttackPower();
			cout << i + 1 << " ";
			cout << itemName << "\tAP: " << weaponAP << endl;
		}
	}

	cout << "\nArmor:" << endl;
	for(int i = 0; i < 2; i++)
	{
		if(p1.armors[i].GetItemName() != "")
		{
			string itemName = p1.armors[i].GetItemName();
			int armorDEF = p1.armors[i].GetDefense();
			cout << i + 1 << " ";
			cout << itemName << "\tDEF: " << armorDEF << endl;
		}
	}

	cout << "\nItems:" << endl;
	for(int i = 0; i < 5; i++)
	{
		if(p1.items[i].GetItemName() != "")
		{
			string itemName = p1.weapons[i].GetItemName();
			double cost = p1.weapons[i].GetCost();
			cout << itemName << "\tCost: " << cost << endl;
		}
	}

	cout << "\n\nHP: " << p1.GetHealth() << endl;
	cout << "Cash: $" << p1.GetCash();

	// TODO:
	//		Ask player if they want to equip a weapon or armor
	//			if so what do they want to replace an equiped weapon/armor with
	//		If they don't wish to exit
	cout << "\n\nTo equip a weapon enter 1";
	cout << "\nTo equip armor enter 2";
	cout << "\nAfterwards enter the number by the item";
	cout << "\nEnter <0> to exit inventory: ";
	input = InputCheck(input);

	switch(input)
	{
		case 0:
			input = -1;
			break;
		case 1:
			input = InputCheck(input);
			switch(input)
			{
				case 0:
					input = -1;
					break;
				case 1:
					wTemp = p1.weaponEquiped;
					p1.weaponEquiped = p1.weapons[0];
					p1.weapons[0] = wTemp;
					break;
				case 2:
					wTemp = p1.weaponEquiped;
					p1.weaponEquiped = p1.weapons[1];
					p1.weapons[1] = wTemp;
					break;
				case 3:
					wTemp = p1.weaponEquiped;
					p1.weaponEquiped = p1.weapons[2];
					p1.weapons[2] = wTemp;
					break;
				default:
					break;
			}
			break;
		case 2:
			input = InputCheck(input);
			switch(input)
			{
				case 0:
					input = -1;
					break;
				case 1:
					aTemp = p1.armorEquiped;
					p1.armorEquiped = p1.armors[0];
					p1.armors[0] = aTemp;
					break;
				case 2:
					aTemp = p1.armorEquiped;
					p1.armorEquiped = p1.armors[1];
					p1.armors[1] = aTemp;
					break;
				default:
					break;
			}
			break;
	}
	cout << "\nPress Enter to continue...";
	cin.clear();
	cin;
	cin.clear();
	cin.ignore(100, '\n');
}

/*
* LoadGame
* no parameters
* opens the saved text file gets the data piece by piece
* takes the data and writes the data into the specific places in memory

void LoadGame()
{
	// TODO:
	//		?Utilize pointer to override for each weapon and armor
	//			instead of creating arse ton of variables

	ifstream myFile;
	string line;
	int num;
	double dub;

	myFile.open("CharacterData.txt");
	if(myFile.is_open())
	{
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		p1.SetName(line);
		p1.SetCash(dub);
		p1.SetHealth(num);
		myFile >> num;
		p1.SetHealthModifier(num);

		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Weapon w (line, dub, num);
		p1.weaponEquiped = w;

		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Armor a (line, dub, num);
		p1.armorEquiped = a;

		// inventory weapons
		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Weapon w1 (line, dub, num);
		p1.weapons[0] = w1;

		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Weapon w2 (line, dub, num);
		p1.weapons[1] = w2;

		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Weapon w3 (line, dub, num);
		p1.weapons[2] = w3;

		// inventory armors
		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Armor a1 (line, dub, num);
		p1.armors[0] = a1;

		myFile.get();
		getline(myFile,line);
		myFile >> dub;
		myFile >> num;
		Armor a2 (line, dub, num);
		p1.armors[1] = a2;

		myFile.close();
	}
}

/* 
* SaveGame 
* no parameters
* takes the players data along with weapons and writes them
* to a text file to be reloaded later

void SaveGame()
{
	system("cls");
	cout << "Do you wish to save before you exit <y or n> ? ";
	name  = InputCheck(name);

	if((name == "y") || (name == "Y"))
	{
		char fileName[100];
		fstream myFile;
		
		/*cout << "Enter file name: ";
		cin >> fileName;
		cout << endl;
		for(int i = 0; i < 100; i++)
		{
			if(fileName[i] == '\n')
			{
				fileName[i] = '.';
				fileName[i + 1] = 't';
				fileName[i + 2] = 'x';
				fileName[i + 3] = 't';
				fileName[i + 4] = '\n';
			}
		}

		myFile.open("CharacterData.txt", ios::out);
		if(myFile.is_open())
		{
			myFile << p1.GetName() << "\n";
			myFile << p1.GetCash() << "\n";
			myFile << p1.GetHealth() << "\n";
			myFile << p1.GetHealthModifier() << "\n";
			myFile << p1.weaponEquiped.GetItemName() << "\n";
			myFile << p1.weaponEquiped.GetCost() << "\n";
			myFile << p1.weaponEquiped.GetAttackPower() << "\n";
			myFile << p1.armorEquiped.GetItemName() << "\n";
			myFile << p1.armorEquiped.GetCost() << "\n";
			myFile << p1.armorEquiped.GetDefense() << "\n";

			for(int i = 0; i < 3; i++)
			{
				myFile << p1.weapons[i].GetItemName() << "\n";
				myFile << p1.weapons[i].GetCost() << "\n";
				myFile << p1.weapons[i].GetAttackPower() << "\n";
			}

			for(int i = 0; i < 2; i++)
			{
				myFile << p1.armors[i].GetItemName() << "\n";
				myFile << p1.armors[i].GetCost() << "\n";
				myFile << p1.armors[i].GetDefense() << "\n";
			}

			for(int i = 0; i < 5; i++)
			{
				myFile << p1.items[i].GetItemName() << "\n";
				myFile << p1.items[i].GetCost() << "\n";
			}

			myFile.close();
		}
	}
}

/* 
* RandomNumber 
* int max and min to generate random numbers between
* generates a random number

int RandomNumber(int maximum, int minimum)
{
	int rand_num = 0;

	rand_num = ((rand()%maximum) + minimum); 

	return rand_num;
}

/* 
* InputCheck 
* takes in string input for character naming and class selection
* gets input while cin fails
*
string InputCheck(string i)
{
	do 
	{
		cin >> i;
		cin.clear();
		cin.ignore(100, '\n');
	} while (cin.fail());

	return i;
}

/* 
* InputCheck
* takes in int input for values
* gets input while cin fails

int InputCheck(int i)
{
	do 
	{
		cin >> i;
		cin.clear();
		cin.ignore(100, '\n');
	} while (cin.fail());
	

	return i;
}
*/